package com.zhiwei.codesecurity.service.schedulejob;

import com.zhiwei.codesecurity.common.constants.Constants;
import com.zhiwei.codesecurity.common.utils.BeanUtil;
import com.zhiwei.codesecurity.common.utils.IdWorker;
import com.zhiwei.codesecurity.common.utils.ScheduleUtils;
import com.zhiwei.codesecurity.entity.ScheduleJob;
import com.zhiwei.codesecurity.entity.ScheduleJobSystem;
import com.zhiwei.codesecurity.mapper.ScheduleJobDao;
import com.zhiwei.codesecurity.mapper.ScheduleJobSystemDao;
import org.apache.commons.collections.CollectionUtils;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

@Service("scheduleJobService")
public class ScheduleJobServiceImpl implements ScheduleJobService {
    /** 调度工厂Bean */
    @Autowired
    private Scheduler scheduler;

    /** 调度工厂 **/
    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Autowired
    private ScheduleJobDao scheduleJobDao;

    @Autowired
    private ScheduleJobSystemDao scheduleJobSystemDao;

    public void initScheduleJobSystem() {
        ScheduleJobSystem scheduleJobCond = new ScheduleJobSystem();
        scheduleJobCond.setStatus(Constants.SCHEDULE_JOB_STATE_RUN);
        List<ScheduleJobSystem> scheduleJobSystemList = scheduleJobSystemDao.list(scheduleJobCond);
        if (CollectionUtils.isEmpty(scheduleJobSystemList)) {
            return;
        }

        for (ScheduleJobSystem scheduleJobSystem : scheduleJobSystemList) {

            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler,
                    scheduleJobSystem.getJobName(), scheduleJobSystem.getJobGroup());

            //不存在，创建一个
            ScheduleJob scheduleJob = new ScheduleJob();
            BeanUtil.copyPropertiesQuietly(scheduleJobSystem, scheduleJob);
            if (cronTrigger == null) {

                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
            } else {
                //已存在，那么更新相应的定时设置
                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
            }
        }
    }

    public void initScheduleJob() {
        ScheduleJob scheduleJobCond = new ScheduleJob();
        scheduleJobCond.setStatus(Constants.SCHEDULE_JOB_STATE_RUN);
        List<ScheduleJob> scheduleJobList = scheduleJobDao.list(scheduleJobCond);
        if (CollectionUtils.isEmpty(scheduleJobList)) {
            return;
        }

        for (ScheduleJob scheduleJob : scheduleJobList) {

            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler,
                    scheduleJob.getJobName(), scheduleJob.getJobGroup());

            //不存在，创建一个
            if (cronTrigger == null) {
                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
            } else {
                //已存在，那么更新相应的定时设置
                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
            }
        }
    }

    public void StartScheduleJob(ScheduleJob scheduleJob) {
        CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler,
                scheduleJob.getJobName(), scheduleJob.getJobGroup());

        //不存在，创建一个
        if (cronTrigger == null) {
            ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
        } else {
            //已存在，那么更新相应的定时设置
            ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
        }
    }

    public Integer insert(ScheduleJob scheduleJob) {
        //create schedule job
        scheduleJob.setScheduleJobId(IdWorker.generate());
        CronTrigger trigger = ScheduleUtils.createScheduleJob(scheduler, scheduleJob);


        if (StringUtils.isEmpty(trigger))
            return null;

        if (StringUtils.isEmpty(scheduleJob.getCronExpression())) {
            scheduleJob.setCronExpression(trigger.getCronExpression());
        }

        //初始化任务执行时间
        Date date = trigger.getNextFireTime();
        scheduleJob.setExecTime(date);
        scheduleJob.setNextExecTime(date);

        return scheduleJobDao.add(scheduleJob);
    }

    public void update(ScheduleJob scheduleJob) {
        ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
        scheduleJobDao.update(scheduleJob);
    }

    public void delUpdate(ScheduleJob scheduleJob) {
        //先删除JOB任务
        ScheduleUtils.deleteScheduleJob(scheduler, scheduleJob.getJobName(),
                scheduleJob.getJobGroup());
        //再创建
        ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
        //数据库直接更新即可
//        scheduleJobDao.updateByScheduleId(scheduleJob);
        scheduleJobDao.update(scheduleJob);
    }

    public void delete(Long scheduleJobId) {
        ScheduleJob scheduleJob = this.get(scheduleJobId);
        if (scheduleJob == null)
            return;

        //删除运行的任务
        ScheduleUtils.deleteScheduleJob(scheduler, scheduleJob.getJobName(),
                scheduleJob.getJobGroup());

        //删除数据
        scheduleJobDao.deleteByPrimaryKey(scheduleJob.getId());
    }

    public void runOnce(Long scheduleJobId) {
        ScheduleJob scheduleJob = this.get(scheduleJobId);
        ScheduleUtils.runOnce(scheduler, scheduleJob.getJobName(), scheduleJob.getJobGroup());
    }

    /**
     * 暂停任务
     * @param scheduleJobId the schedule job id
     */
    public void pauseJob(Long scheduleJobId) throws Exception {
        ScheduleJob scheduleJob = this.get(scheduleJobId);
        if (scheduleJob == null)
            return;

        ScheduleUtils.pauseJob(scheduler, scheduleJob.getJobName(), scheduleJob.getJobGroup());
        //数据更新状态
        updateScheduleState(scheduleJob.getId(), Constants.SCHEDULE_JOB_STATE_STOP);
    }

    /**
     * 恢复任务
     * @param scheduleJobId the schedule job id
     */
    public void resumeJob(Long scheduleJobId) throws Exception {
        ScheduleJob scheduleJob = get(scheduleJobId);
        if (scheduleJob == null)
            return;

        ScheduleUtils.resumeJob(scheduler, scheduleJob.getJobName(), scheduleJob.getJobGroup());
        //数据更新状态
        updateScheduleState(scheduleJob.getId(), Constants.SCHEDULE_JOB_STATE_RUN);
    }

    private boolean updateScheduleState(Long id, String status) throws Exception {
        ScheduleJob scheduleJobNew = new ScheduleJob();
        scheduleJobNew.setId(id);
        scheduleJobNew.setStatus(status);

        return scheduleJobDao.update(scheduleJobNew)>0 ? true : false;
    }

    /**
     * 根据ID获取任务
     * @param scheduleJobId
     * @return
     */
    public ScheduleJob get(Long scheduleJobId) {
        ScheduleJob scheduleJobCond = new ScheduleJob();
        scheduleJobCond.setScheduleJobId(scheduleJobId);

        List<ScheduleJob> jobs = scheduleJobDao.list(scheduleJobCond);
        return (jobs != null && !jobs.isEmpty()) ? jobs.get(0):null;
    }

    public List<ScheduleJob> queryList(ScheduleJob scheduleJob) {
//        ScheduleJobDOCriteria example = new ScheduleJobDOCriteria();
//        example.setOrderByClause("GMT_CREATE desc");
//        List<ScheduleJob> scheduleJobs = scheduleJobDao.selectByExample(example);
        List<ScheduleJob> scheduleJobs = scheduleJobDao.list(new ScheduleJob());// 查询全部

        //List<ScheduleJobDO> scheduleJobVoList = BeanConverter.convert(ScheduleJobVo.class, scheduleJobs);
        /*try {
            //quartz 中获取任务状态及表达式
            for (ScheduleJobDO vo : scheduleJobs) {

                JobKey jobKey = ScheduleUtils.getJobKey(vo.getJobName(), vo.getJobGroup());
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                if (CollectionUtils.isEmpty(triggers)) {
                    continue;
                }

                //这里一个任务可以有多个触发器， 但是我们一个任务对应一个触发器，所以只取第一个即可，清晰明了
                Trigger trigger = triggers.iterator().next();
                vo.setJobTrigger(trigger.getKey().getName());

                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                vo.setStatus(triggerState.name());

                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    vo.setCronExpression(cronExpression);
                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }*/

        return scheduleJobs;
    }

    public List<ScheduleJob> queryExecutingJobList() {
        try {
            List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();//获取执行中的定时任务列表
            List<ScheduleJob> jobList = new ArrayList<>(executingJobs.size());

            ScheduleJob job = null;

            for (JobExecutionContext executingJob : executingJobs) {
                job = new ScheduleJob();
                JobDetail jobDetail = executingJob.getJobDetail();
                JobKey jobKey = jobDetail.getKey();

                Trigger trigger = executingJob.getTrigger();
                job.setJobName(jobKey.getName());
                job.setJobGroup(jobKey.getGroup());
                job.setJobTrigger(trigger.getKey()+"");
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                job.setStatus(triggerState.name());
                //执行开始时间
                jobList.add(job);
            }
            return jobList;
        } catch (SchedulerException e) {
            return null;
        }
    }

    @Override
    public List<ScheduleJob> queryQuartzJobList() throws Exception {

        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
        List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
        for (JobKey jobKey : jobKeys) {

            List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
            for (Trigger trigger : triggers) {
                //{ NONE/没有, NORMAL/正常, PAUSED/已暂停, COMPLETE/执行完成, ERROR/异常, BLOCKED/锁住 }
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                //如果不为待执行任务
                /*if (triggerState != Trigger.TriggerState.NORMAL)
                    continue;*/

                ScheduleJob job = new ScheduleJob();
                job.setJobName(jobKey.getName());
                job.setJobGroup(jobKey.getGroup());
                job.setJobTrigger(trigger.getKey()+"");
                job.setStatus(triggerState.name());
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    job.setCronExpression(cronExpression);
                }
                jobList.add(job);
            }
        }
        return jobList;
    }

//    @Override
//    public List<ScheduleJobDO> queryJobListByExample(ScheduleJobDOCriteria example) throws Exception {
//        return scheduleJobDOMapper.selectByExample(example);
//    }

    @Override
    public boolean existsJobName(String jobName) throws Exception {
//        ScheduleJobDOCriteria example = new ScheduleJobDOCriteria();
//        example.createCriteria().andJobNameEqualTo(jobName);
        ScheduleJob scheduleJobCond = new ScheduleJob();
        scheduleJobCond.setJobName(jobName);

//        List<ScheduleJob> result = queryJobListByExample(example);
        List<ScheduleJob> result = scheduleJobDao.list(scheduleJobCond);
        return (result != null && CollectionUtils.isNotEmpty(result)) ? true:false;
    }

}
